﻿using System.Collections.ObjectModel;
using System.Linq;
using System.Timers;
using System.Windows;
using AIStudio.Wpf.DiagramApp.Models;
using AIStudio.Wpf.DiagramDesigner;
using AIStudio.Wpf.SFC;
using AIStudio.Wpf.SFC.ViewModels;

namespace AIStudio.Wpf.DiagramApp.ViewModels
{
    public class SFCViewModel : PageViewModel
    {
        public SFCViewModel(string title, string status, DiagramType diagramType) : base(title, status, diagramType)
        {
            
        }

        public SFCViewModel(string filename, DiagramDocument diagramDocument) : base(filename, diagramDocument)
        {
            if (DiagramViewModel != null)
            {
                SFCService.InitData(DiagramViewModel.Items.OfType<SFCNode>().ToList(), DiagramViewModel.Items.OfType<ConnectionViewModel>().ToList(), DiagramViewModel);
            }
            readDataTimer.Elapsed += timeCycle;
            readDataTimer.Interval = 1000;
            readDataTimer.AutoReset = false;
            readDataTimer.Start();
            _service.DrawModeViewModel.LineDrawMode = DrawMode.ConnectingLineBoundary;
        }

        protected override void InitDiagramViewModel()
        {
            base.InitDiagramViewModel();

            DiagramViewModel.DiagramOption.LayoutOption.ShowGrid = true;
            DiagramViewModel.DiagramOption.LayoutOption.GridCellSize = new Size(100, 60);
            DiagramViewModel.DiagramOption.LayoutOption.CellHorizontalAlignment = CellHorizontalAlignment.Center;
            DiagramViewModel.DiagramOption.LayoutOption.CellVerticalAlignment = CellVerticalAlignment.Center;
            _service.DrawModeViewModel.LineDrawMode = DrawMode.ConnectingLineBoundary;
        }

        private System.Timers.Timer readDataTimer = new System.Timers.Timer();
        protected override void Init(bool initNew)
        {
            base.Init(initNew);

            SFCStartNode start = new SFCStartNode() { Name = nameof(start), Left = 0, Top = 60, Text = "S0" };
            DiagramViewModel.Add(start);

            SFCConditionNode condition1_1 = new SFCConditionNode() { Name = nameof(condition1_1), Left = 0, Top = 120, Text = "X01", Expression = "p0==1&p1<20", LinkPoint = new ObservableCollection<LinkPoint> { SFCService.LinkPoint.FirstOrDefault(p => p.Name == "S0"), SFCService.LinkPoint.FirstOrDefault(p => p.Name == "T2") } };
            DiagramViewModel.Add(condition1_1);

            SFCConditionNode condition1_2 = new SFCConditionNode() { Name = nameof(condition1_2), Left = 100, Top = 120, Text = "X02", Expression = "p0==1&p1<30", LinkPoint = new ObservableCollection<LinkPoint> { SFCService.LinkPoint.FirstOrDefault(p => p.Name == "S0"), SFCService.LinkPoint.FirstOrDefault(p => p.Name == "T2") } };
            DiagramViewModel.Add(condition1_2);

            SFCNodeNode step1 = new SFCNodeNode() { Name = nameof(step1), Left = 0, Top = 180, Text = "S1" };
            DiagramViewModel.Add(step1);

            SFCActionNode action11 = new SFCActionNode() { Name = nameof(action11), Left = 100, Top = 180, Text = "SET_V1", Expression = "1", LinkPoint = SFCService.LinkPoint.FirstOrDefault(p => p.Name == "K1_DI") };
            DiagramViewModel.Add(action11);

            SFCActionNode action12 = new SFCActionNode() {Name = nameof(action12), Left = 200, Top = 180, Text = "SET_V2", Expression = "1", LinkPoint = SFCService.LinkPoint.FirstOrDefault(p => p.Name == "K2_DI") };
            DiagramViewModel.Add(action12);

            SFCActionNode action13 = new SFCActionNode() {Name = nameof(action13), Left = 300, Top = 180, Text = "SET_V3", Expression = "1", LinkPoint = SFCService.LinkPoint.FirstOrDefault(p => p.Name == "K3_DI") };
            DiagramViewModel.Add(action13);

            SFCActionNode action14 = new SFCActionNode() {Name = nameof(action14), Left = 400, Top = 180, Text = "RES_V4", Expression = "0", LinkPoint = SFCService.LinkPoint.FirstOrDefault(p => p.Name == "K4_DI") };
            DiagramViewModel.Add(action14);

            SFCConditionNode condition2 = new SFCConditionNode() {Name = nameof(condition2), Left = 0, Top = 240, Text = "X1", Expression = "p0>50", LinkPoint = new ObservableCollection<LinkPoint> { SFCService.LinkPoint.FirstOrDefault(p => p.Name == "T2") } };
            DiagramViewModel.Add(condition2);

            SFCNodeNode step2 = new SFCNodeNode() {Name = nameof(step2), Left = 0, Top = 300, Text = "S2" };
            DiagramViewModel.Add(step2);

            SFCActionNode action2 = new SFCActionNode() {Name = nameof(action2), Left = 100, Top = 300, Text = "SET_V4", Expression = "1", LinkPoint = SFCService.LinkPoint.FirstOrDefault(p => p.Name == "K4_DI") };
            DiagramViewModel.Add(action2);

            SFCConditionNode condition3 = new SFCConditionNode() {Name = nameof(condition3), Left = 0, Top = 360, Text = "X2", Expression = "p0>70", LinkPoint = new ObservableCollection<LinkPoint> { SFCService.LinkPoint.FirstOrDefault(p => p.Name == "T2") } };
            DiagramViewModel.Add(condition3);

            SFCNodeNode step3 = new SFCNodeNode() { Name = nameof(step3), Left = 0, Top = 420, Text = "S3" };
            DiagramViewModel.Add(step3);

            SFCActionNode action3 = new SFCActionNode() {Name = nameof(action3), Left = 100, Top = 420, Text = "RES_V1", Expression = "0", LinkPoint = SFCService.LinkPoint.FirstOrDefault(p => p.Name == "K1_DI") };
            DiagramViewModel.Add(action3);

            SFCConditionNode condition4 = new SFCConditionNode() {Name = nameof(condition4), Left = 0, Top = 480, Text = "X3", Expression = "p0>80", LinkPoint = new ObservableCollection<LinkPoint> { SFCService.LinkPoint.FirstOrDefault(p => p.Name == "T2") } };
            DiagramViewModel.Add(condition4);

            SFCCOBeginNode cobegin = new SFCCOBeginNode() {Name = nameof(cobegin), Left = 38, Top = 540, Text = "" };
            DiagramViewModel.Add(cobegin);

            SFCNodeNode step4 = new SFCNodeNode() {Name = nameof(step4), Left = 0, Top = 600, Text = "S4" };
            DiagramViewModel.Add(step4);

            SFCActionNode action4 = new SFCActionNode() {Name = nameof(action4), Left = 100, Top = 600, Text = "RES_V2", Expression = "0", LinkPoint = SFCService.LinkPoint.FirstOrDefault(p => p.Name == "K2_DI") };
            DiagramViewModel.Add(action4);

            SFCConditionNode condition5 = new SFCConditionNode() {Name = nameof(condition5), Left = 0, Top = 660, Text = "X4", Expression = "p0==0", LinkPoint = new ObservableCollection<LinkPoint> { SFCService.LinkPoint.FirstOrDefault(p => p.Name == "K2_DO") } };
            DiagramViewModel.Add(condition5);

            SFCNodeNode step5 = new SFCNodeNode() {Name = nameof(step5), Left = 200, Top = 600, Text = "S5" };
            DiagramViewModel.Add(step5);

            SFCActionNode action5 = new SFCActionNode() {Name = nameof(action5), Left = 300, Top = 600, Text = "RES_V3", Expression = "0", LinkPoint = SFCService.LinkPoint.FirstOrDefault(p => p.Name == "K3_DI") };
            DiagramViewModel.Add(action5);

            SFCConditionNode condition6 = new SFCConditionNode() {Name = nameof(condition6), Left = 200, Top = 660, Text = "X5", Expression = "p0==0", LinkPoint = new ObservableCollection<LinkPoint> { SFCService.LinkPoint.FirstOrDefault(p => p.Name == "K3_DO") } };
            DiagramViewModel.Add(condition6);

            SFCCOEndNode coend = new SFCCOEndNode() {Name = nameof(coend), Left = 38, Top = 720, Text = "" };
            DiagramViewModel.Add(coend);

            ConnectionViewModel connector1_1 = new ConnectionViewModel(DiagramViewModel, start.Output[0], condition1_1.Input[0], _service.DrawModeViewModel.LineDrawMode, _service.DrawModeViewModel.LineRouterMode) { Name = nameof(connector1_1), };
            DiagramViewModel.Add(connector1_1);

            ConnectionViewModel connector2_1 = new ConnectionViewModel(DiagramViewModel, condition1_1.Output[0], step1.Input[0], _service.DrawModeViewModel.LineDrawMode, _service.DrawModeViewModel.LineRouterMode) { Name = nameof(connector2_1), };
            DiagramViewModel.Add(connector2_1);

            ConnectionViewModel connector1_2 = new ConnectionViewModel(DiagramViewModel, start.Output[0], condition1_2.Input[0], _service.DrawModeViewModel.LineDrawMode, _service.DrawModeViewModel.LineRouterMode) { Name = nameof(connector1_2) };
            DiagramViewModel.Add(connector1_2);

            ConnectionViewModel connector2_2 = new ConnectionViewModel(DiagramViewModel, condition1_2.Output[0], step1.Input[0], _service.DrawModeViewModel.LineDrawMode, _service.DrawModeViewModel.LineRouterMode) { Name = nameof(connector2_2) };
            DiagramViewModel.Add(connector2_2);

            ConnectionViewModel connector31 = new ConnectionViewModel(DiagramViewModel, step1.Action[0], action11.Input[0], _service.DrawModeViewModel.LineDrawMode, _service.DrawModeViewModel.LineRouterMode) { Name = nameof(connector31), };
            DiagramViewModel.Add(connector31);

            ConnectionViewModel connector32 = new ConnectionViewModel(DiagramViewModel, step1.Action[0], action12.Input[0], _service.DrawModeViewModel.LineDrawMode, _service.DrawModeViewModel.LineRouterMode) { Name = nameof(connector32) };
            DiagramViewModel.Add(connector32);

            ConnectionViewModel connector33 = new ConnectionViewModel(DiagramViewModel, step1.Action[0], action13.Input[0], _service.DrawModeViewModel.LineDrawMode, _service.DrawModeViewModel.LineRouterMode) { Name = nameof(connector33) };
            DiagramViewModel.Add(connector33);

            ConnectionViewModel connector34 = new ConnectionViewModel(DiagramViewModel, step1.Action[0], action14.Input[0], _service.DrawModeViewModel.LineDrawMode, _service.DrawModeViewModel.LineRouterMode) { Name = nameof(connector34) };
            DiagramViewModel.Add(connector34);

            ConnectionViewModel connector4 = new ConnectionViewModel(DiagramViewModel, step1.Output[0], condition2.Input[0], _service.DrawModeViewModel.LineDrawMode, _service.DrawModeViewModel.LineRouterMode) { Name = nameof(connector4) };
            DiagramViewModel.Add(connector4);

            ConnectionViewModel connector5 = new ConnectionViewModel(DiagramViewModel, condition2.Output[0], step2.Input[0], _service.DrawModeViewModel.LineDrawMode, _service.DrawModeViewModel.LineRouterMode) { Name = nameof(connector5) };
            DiagramViewModel.Add(connector5);

            ConnectionViewModel connector6 = new ConnectionViewModel(DiagramViewModel, step2.Action[0], action2.Input[0], _service.DrawModeViewModel.LineDrawMode, _service.DrawModeViewModel.LineRouterMode) { Name = nameof(connector6) };
            DiagramViewModel.Add(connector6);

            ConnectionViewModel connector7 = new ConnectionViewModel(DiagramViewModel, step2.Output[0], condition3.Input[0], _service.DrawModeViewModel.LineDrawMode, _service.DrawModeViewModel.LineRouterMode) { Name = nameof(connector7) };
            DiagramViewModel.Add(connector7);

            ConnectionViewModel connector8 = new ConnectionViewModel(DiagramViewModel, condition3.Output[0], step3.Input[0], _service.DrawModeViewModel.LineDrawMode, _service.DrawModeViewModel.LineRouterMode) { Name = nameof(connector8) };
            DiagramViewModel.Add(connector8);

            ConnectionViewModel connector9 = new ConnectionViewModel(DiagramViewModel, step3.Action[0], action3.Input[0], _service.DrawModeViewModel.LineDrawMode, _service.DrawModeViewModel.LineRouterMode) { Name = nameof(connector9) };
            DiagramViewModel.Add(connector9);

            ConnectionViewModel connector10 = new ConnectionViewModel(DiagramViewModel, step3.Output[0], condition4.Input[0], _service.DrawModeViewModel.LineDrawMode, _service.DrawModeViewModel.LineRouterMode) { Name = nameof(connector10) };
            DiagramViewModel.Add(connector10);

            ConnectionViewModel connector11 = new ConnectionViewModel(DiagramViewModel, condition4.Output[0], cobegin.Input[0], _service.DrawModeViewModel.LineDrawMode, _service.DrawModeViewModel.LineRouterMode) { Name = nameof(connector11) };
            DiagramViewModel.Add(connector11);

            ConnectionViewModel connector12 = new ConnectionViewModel(DiagramViewModel, cobegin.Output[0], step4.Input[0], _service.DrawModeViewModel.LineDrawMode, _service.DrawModeViewModel.LineRouterMode) { Name = nameof(connector12) };
            DiagramViewModel.Add(connector12);

            ConnectionViewModel connector13 = new ConnectionViewModel(DiagramViewModel, step4.Action[0], action4.Input[0], _service.DrawModeViewModel.LineDrawMode, _service.DrawModeViewModel.LineRouterMode) { Name = nameof(connector13) };
            DiagramViewModel.Add(connector13);

            ConnectionViewModel connector14 = new ConnectionViewModel(DiagramViewModel, step4.Output[0], condition5.Input[0], _service.DrawModeViewModel.LineDrawMode, _service.DrawModeViewModel.LineRouterMode) { Name = nameof(connector14) };
            DiagramViewModel.Add(connector14);

            ConnectionViewModel connector15 = new ConnectionViewModel(DiagramViewModel, cobegin.Output[1], step5.Input[0], _service.DrawModeViewModel.LineDrawMode, _service.DrawModeViewModel.LineRouterMode) { Name = nameof(connector15), };
            DiagramViewModel.Add(connector15);

            ConnectionViewModel connector16 = new ConnectionViewModel(DiagramViewModel, step5.Action[0], action5.Input[0], _service.DrawModeViewModel.LineDrawMode, _service.DrawModeViewModel.LineRouterMode) { Name = nameof(connector16), };
            DiagramViewModel.Add(connector16);

            ConnectionViewModel connector17 = new ConnectionViewModel(DiagramViewModel, step5.Output[0], condition6.Input[0], _service.DrawModeViewModel.LineDrawMode, _service.DrawModeViewModel.LineRouterMode) { Name = nameof(connector17), };
            DiagramViewModel.Add(connector17);

            ConnectionViewModel connector18 = new ConnectionViewModel(DiagramViewModel, condition5.Output[0], coend.Input[0], _service.DrawModeViewModel.LineDrawMode, _service.DrawModeViewModel.LineRouterMode) { Name = nameof(connector18), };
            DiagramViewModel.Add(connector18);

            ConnectionViewModel connector19 = new ConnectionViewModel(DiagramViewModel, condition6.Output[0], coend.Input[1], _service.DrawModeViewModel.LineDrawMode, _service.DrawModeViewModel.LineRouterMode) { Name = nameof(connector19), };
            DiagramViewModel.Add(connector19);

            ConnectionViewModel connector20 = new ConnectionViewModel(DiagramViewModel, coend.Output[0], start.Input[0], _service.DrawModeViewModel.LineDrawMode, _service.DrawModeViewModel.LineRouterMode) { Name = nameof(connector20), };
            DiagramViewModel.Add(connector20);

            #region 模拟部分
            TextDesignerItemViewModel despcription = new TextDesignerItemViewModel()
            {
                Name = nameof(despcription),
                Left = 230,
                Top = 270,
                ItemWidth = 300,
                ItemHeight = 120,
                Text = @"模拟一个容器的高低液位控制方法
1.按下启动按钮, 程序启动
2.当液位低于20%的时候, V1,V2,V3打开, V4关闭
3.当液位高于50%的时候, V4打开
4.当液位高于70%的时侯, V1关闭
5.当液位高于80%的时候, V2,V3并行关闭"
            };
            despcription.FontViewModel.HorizontalAlignment = HorizontalAlignment.Left;
            despcription.FontViewModel.VerticalAlignment = VerticalAlignment.Top;
            DiagramViewModel.Add(despcription);

            Simulate_ListViewModel list = new Simulate_ListViewModel()
            {
                Name = nameof(list),
                Left = 410,
                Top = 390,
            };
            DiagramViewModel.Add(list);

            Simulate_StartViewModel btnstart = new Simulate_StartViewModel() { Name = nameof(btnstart), Left = 0, Top = 0, LinkPoint = SFCService.LinkPoint.FirstOrDefault(p => p.Name == "S0"), };
            DiagramViewModel.Add(btnstart);

            Simulate_TankViewModel tank1 = new Simulate_TankViewModel() {Name = nameof(tank1), Left = 100, Top = 43, ItemWidth = 48, ItemHeight = 60, Text = "T1", LinkPoint = SFCService.LinkPoint.FirstOrDefault(p => p.Name == "T1") };
            DiagramViewModel.Add(tank1);

            Simulate_SolenoidViewModel k1 = new Simulate_SolenoidViewModel() {Name = nameof(k1),  Left = 200, Top = 0, Text = "K1", DILinkPoint = SFCService.LinkPoint.FirstOrDefault(p => p.Name == "K1_DI"), DOLinkPoint = SFCService.LinkPoint.FirstOrDefault(p => p.Name == "K1_DO") };
            DiagramViewModel.Add(k1);

            Simulate_SolenoidViewModel k2 = new Simulate_SolenoidViewModel() {Name = nameof(k2), Left = 200, Top = 60, Text = "K2", DILinkPoint = SFCService.LinkPoint.FirstOrDefault(p => p.Name == "K2_DI"), DOLinkPoint = SFCService.LinkPoint.FirstOrDefault(p => p.Name == "K2_DO") };
            DiagramViewModel.Add(k2);

            Simulate_SolenoidViewModel k3 = new Simulate_SolenoidViewModel() {Name = nameof(k3), Left = 200, Top = 120, Text = "K3", DILinkPoint = SFCService.LinkPoint.FirstOrDefault(p => p.Name == "K3_DI"), DOLinkPoint = SFCService.LinkPoint.FirstOrDefault(p => p.Name == "K3_DO") };
            DiagramViewModel.Add(k3);

            Simulate_TankViewModel tank2 = new Simulate_TankViewModel() {Name = nameof(tank2), Left = 300, Top = 28, Text = "T2", LinkPoint = SFCService.LinkPoint.FirstOrDefault(p => p.Name == "T2") };

            DiagramViewModel.Add(tank2);

            Simulate_SolenoidViewModel k4 = new Simulate_SolenoidViewModel() {Name = nameof(k4), Left = 400, Top = 60, Text = "K4", DILinkPoint = SFCService.LinkPoint.FirstOrDefault(p => p.Name == "K4_DI"), DOLinkPoint = SFCService.LinkPoint.FirstOrDefault(p => p.Name == "K4_DO") };
            DiagramViewModel.Add(k4);

            Simulate_TankViewModel tank3 = new Simulate_TankViewModel() {Name = nameof(tank3), Left = 500, Top = 103, ItemWidth = 48, ItemHeight = 60, Text = "T3", LinkPoint = SFCService.LinkPoint.FirstOrDefault(p => p.Name == "T3") };
            DiagramViewModel.Add(tank3);

            ConnectionViewModel conn1 = new ConnectionViewModel(DiagramViewModel, tank1.Output[0], k1.Input[0], _service.DrawModeViewModel.LineDrawMode, _service.DrawModeViewModel.LineRouterMode) { Name = nameof(conn1), };
            DiagramViewModel.Add(conn1);

            ConnectionViewModel conn2 = new ConnectionViewModel(DiagramViewModel, tank1.Output[0], k2.Input[0], _service.DrawModeViewModel.LineDrawMode, _service.DrawModeViewModel.LineRouterMode) { Name = nameof(conn2) };
            DiagramViewModel.Add(conn2);

            ConnectionViewModel conn3 = new ConnectionViewModel(DiagramViewModel, tank1.Output[0], k3.Input[0], _service.DrawModeViewModel.LineDrawMode, _service.DrawModeViewModel.LineRouterMode) { Name = nameof(conn3) };
            DiagramViewModel.Add(conn3);

            ConnectionViewModel conn4 = new ConnectionViewModel(DiagramViewModel, k1.Output[0], tank2.Input[0], _service.DrawModeViewModel.LineDrawMode, _service.DrawModeViewModel.LineRouterMode) { Name = nameof(conn4) };
            DiagramViewModel.Add(conn4);

            ConnectionViewModel conn5 = new ConnectionViewModel(DiagramViewModel, k2.Output[0], tank2.Input[0], _service.DrawModeViewModel.LineDrawMode, _service.DrawModeViewModel.LineRouterMode) { Name = nameof(conn5) };
            DiagramViewModel.Add(conn5);

            ConnectionViewModel conn6 = new ConnectionViewModel(DiagramViewModel, k3.Output[0], tank2.Input[0], _service.DrawModeViewModel.LineDrawMode, _service.DrawModeViewModel.LineRouterMode) { Name = nameof(conn6) };
            DiagramViewModel.Add(conn6);

            ConnectionViewModel conn7 = new ConnectionViewModel(DiagramViewModel, tank2.Output[1], k4.Input[0], _service.DrawModeViewModel.LineDrawMode, _service.DrawModeViewModel.LineRouterMode) { Name = nameof(conn7), };
            DiagramViewModel.Add(conn7);

            ConnectionViewModel conn8 = new ConnectionViewModel(DiagramViewModel, k4.Output[0], tank3.Input[0], _service.DrawModeViewModel.LineDrawMode, _service.DrawModeViewModel.LineRouterMode) { Name = nameof(conn8) };
            DiagramViewModel.Add(conn8);
            #endregion

            SFCService.InitData(DiagramViewModel.Items.OfType<SFCNode>().ToList(), DiagramViewModel.Items.OfType<ConnectionViewModel>().ToList(), DiagramViewModel);

            readDataTimer.Elapsed += timeCycle;
            readDataTimer.Interval = 1000;
            readDataTimer.AutoReset = false;
            readDataTimer.Start();
        }

        private void timeCycle(object sender, ElapsedEventArgs e)
        {
            if (DiagramViewModel != null)
            {
                SFCService.Execute(DiagramViewModel);
            }
            readDataTimer.Start();
        }

        public override void Dispose()
        {
            base.Dispose();

            readDataTimer.Stop();
            readDataTimer.Dispose();

            foreach (var viewModel in DiagramViewModels)
            {
                SFCService.Dispose(viewModel);
            }
        }
    }
}
